﻿using System;
using System.IO;
using System.Windows.Threading;

namespace Utilities.Logging {
    public class ocLogger {

        public enum eLoggingMode { Single, Continuous, TimedHybrid };

        private bool flag_DefaultFilenameSet;
        private eLoggingMode flag_DefaultLoggingMode;
        private bool flag_ContinuousEntryOpen;
        private bool flag_AutoCloseContinuousEntry;

        private string memory_DefaultFilename;
        private string memory_OpenFilename;
        private int memory_HybridBreakTime;
        private int memory_HybridBreakTimeLeft;

        private FileStream memory_Stream;
        private StreamWriter memory_Writer;

        private DispatcherTimer memory_Timer;

        // ####################################################
        // #####    Object Initialization
        // ####################################################
        #region Object Initialization

        public ocLogger() {
            do_Initialize();
            do_Preset();
            do_Startup();
        }

        ~ocLogger() {
            do_Finalize();
        }

        private void do_Initialize() {

        }

        private void do_Preset() {
            flag_DefaultFilenameSet = false;
            flag_DefaultLoggingMode = eLoggingMode.Single;
            flag_ContinuousEntryOpen = false;
            flag_AutoCloseContinuousEntry = false;
        }

        private void do_Startup() {

        }

        private void do_Finalize() {
            if (Flag_DefaultLoggingMode == eLoggingMode.Continuous) {
                if (flag_ContinuousEntryOpen) close_ContinuousLog();
            }
            else if (Flag_DefaultLoggingMode == eLoggingMode.TimedHybrid) {
                if (flag_ContinuousEntryOpen) close_TimedHybridLog();
            }
        }

        #endregion

        // ####################################################
        // #####    Public Access
        // ####################################################
        #region Public Access

        public bool Flag_DefaultFilenameSet {
            get {
                return flag_DefaultFilenameSet;
            }
        }

        public eLoggingMode Flag_DefaultLoggingMode {
            get {
                return flag_DefaultLoggingMode;
            }
        }

        public bool Flag_ContinuousEntryOpen {
            get {
                return flag_ContinuousEntryOpen;
            }
        }

        public bool Flag_AutoCloseContinuousEntry {
            get {
                return flag_AutoCloseContinuousEntry;
            }
            set {
                flag_AutoCloseContinuousEntry = value;
            }
        }

        public string Setting_DefaultFilename {
            get {
                return memory_DefaultFilename;
            }
            set {
                memory_DefaultFilename = value;
            }
        }

        public string Setting_OpenFilename {
            get {
                return memory_OpenFilename;
            }
        }

        public bool Log_Single(string sFilename, string sText) {
            return do_SingleLog(sFilename, sText);
        }

        public bool Start_ContinuousLog(string sFilename) {
            if (flag_DefaultLoggingMode == eLoggingMode.Continuous) {
                // disable first
                close_ContinuousLog();
            }
            else if (flag_DefaultLoggingMode == eLoggingMode.TimedHybrid) {
                // disable first
                close_TimedHybridLog();
            }
            // enable
            return open_ContinuousLog(sFilename);
        }

        public bool Stop_ContinuousLog() {
            if (flag_DefaultLoggingMode == eLoggingMode.Continuous) {
                return close_ContinuousLog();
            }
            return false;
        }

        public bool Start_TimedHybridLog(string sFilename, int iSeconds) {
            if (flag_DefaultLoggingMode == eLoggingMode.Continuous) {
                // disable first
                close_ContinuousLog();
            }
            else if (flag_DefaultLoggingMode == eLoggingMode.TimedHybrid) {
                // disable first
                close_TimedHybridLog();
            }
            // create timer
            if (memory_Timer == null) {
                memory_Timer = new DispatcherTimer();
                memory_Timer.Interval = TimeSpan.FromSeconds(1.0);
                memory_Timer.Tick += ev_Timer_Tick;
            }
            // enable
            return open_TimedHybidLog(sFilename, iSeconds);
        }

        public bool Stop_TimedHybridLog() {
            if (flag_DefaultLoggingMode == eLoggingMode.TimedHybrid) {
                return close_TimedHybridLog();
            }
            return false;
        }

        public bool Log(string sText) {
            switch (flag_DefaultLoggingMode) {
                case eLoggingMode.Single:
                    return do_SingleLog(memory_DefaultFilename, sText);
                case eLoggingMode.Continuous:
                    return do_ContinuousLog(sText);
                case eLoggingMode.TimedHybrid:
                    if (flag_ContinuousEntryOpen) {
                        memory_HybridBreakTimeLeft = memory_HybridBreakTime;
                        return do_TimedHybridLog(sText);
                    } else {
                        resume_TimedHybridLog();
                        return do_TimedHybridLog(sText);
                    }
                default:

                    return false;
            }
        }

        #endregion

        // ####################################################
        // #####    Private Functions
        // ####################################################
        #region Private Functions

        private bool do_SingleLog(string sFilename, string sText) {
            FileStream oStream = null;
            StreamWriter oWriter= null;
            FileInfo oFInfo = new FileInfo(sFilename);
            bool bError = false;

            try {
                if (oFInfo.Exists) oStream = new FileStream(sFilename, FileMode.Append);
                else oStream = new FileStream(sFilename, FileMode.OpenOrCreate);
                oWriter = new StreamWriter(oStream);
                oWriter.WriteLine(sText);
            }
            catch (Exception oException) {
                bError = true;
#if DEBUG
                System.Windows.MessageBox.Show("An error occured while trying to log.\n\n" + oException.StackTrace, "Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
#endif
            }
            finally {
                if (oStream != null) oStream.Close();
                if (oWriter != null) oWriter.Close();
            }
            return bError ? false : true;
        }

        private bool open_ContinuousLog(string sFilename) {
            if (flag_DefaultLoggingMode == eLoggingMode.Single) {
                if (!flag_ContinuousEntryOpen) {
                    FileInfo oFInfo = new FileInfo(sFilename);
                    try {
                        if (oFInfo.Exists) memory_Stream = new FileStream(sFilename, FileMode.Append);
                        else memory_Stream = new FileStream(sFilename, FileMode.OpenOrCreate);
                        memory_Writer = new StreamWriter(memory_Stream);
                    }
                    catch (Exception oException) {
#if DEBUG
                        System.Windows.MessageBox.Show("An error occured while trying to open file '" + sFilename + "'.\n\n" + oException.StackTrace, "Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
#endif
                    }
                    flag_DefaultLoggingMode = eLoggingMode.Continuous;
                    flag_ContinuousEntryOpen = true;
                    memory_OpenFilename = sFilename;
                    return true;
                }
            }
            return false;
        }

        private bool do_ContinuousLog(string sText) {
            if (flag_DefaultLoggingMode == eLoggingMode.Continuous) {
                if (flag_ContinuousEntryOpen) {
                    try {
                        memory_Writer.WriteLine(sText);
                    }
                    catch (Exception oException) {
#if DEBUG
                        System.Windows.MessageBox.Show("An error occured while trying to log.\n\n" + oException.StackTrace, "Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
#endif
                        return false;
                    }
                    return true;
                }
            }
            return false;
        }

        private bool close_ContinuousLog() {
            if (flag_DefaultLoggingMode == eLoggingMode.Continuous) {
                if (flag_ContinuousEntryOpen) {
                    try {
                        if (memory_Writer != null) memory_Writer.Close();
                        if (memory_Stream != null) memory_Stream.Close();
                    }
                    catch (Exception oException) {
#if DEBUG
                        System.Windows.MessageBox.Show("An error occured while trying to close a log.\n\n" + oException.StackTrace, "Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
#endif
                        if (memory_Stream != null) memory_Stream.Close();
                    }
                    flag_DefaultLoggingMode = eLoggingMode.Single;
                    flag_ContinuousEntryOpen = false;
                    memory_OpenFilename = null;
                    memory_Stream = null;
                    memory_Writer = null;
                    return true;

                }
            }
            return false;
        }


        private bool open_TimedHybidLog(string sFilename, int iSeconds) {
            if (flag_DefaultLoggingMode == eLoggingMode.Single) {
                if (!flag_ContinuousEntryOpen) {
                    FileInfo oFInfo = new FileInfo(sFilename);
                    try {
                        if (oFInfo.Exists) memory_Stream = new FileStream(sFilename, FileMode.OpenOrCreate);
                        else memory_Stream = new FileStream(sFilename, FileMode.OpenOrCreate);
                        memory_Writer = new StreamWriter(memory_Stream);
                    }
                    catch (Exception oException) {
#if DEBUG
                        System.Windows.MessageBox.Show("An error occured while trying to open file '" + sFilename + "'.\n\n" + oException.Message + "\n\n" + oException.StackTrace, "Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
#endif
                    }
                    flag_DefaultLoggingMode = eLoggingMode.TimedHybrid;
                    memory_HybridBreakTime = iSeconds;
                    memory_HybridBreakTimeLeft = iSeconds;
                    flag_ContinuousEntryOpen = true;
                    memory_OpenFilename = sFilename;
                    memory_Timer.Start();
                    return true;
                }
            }
            return false;
        }

        private bool do_TimedHybridLog(string sText) {
            if (flag_DefaultLoggingMode == eLoggingMode.TimedHybrid) {
                if (flag_ContinuousEntryOpen) {
                    try {
                        memory_Writer.WriteLine(sText);
                    }
                    catch (Exception oException) {
#if DEBUG
                        System.Windows.MessageBox.Show("An error occured while trying to log.\n\n" + oException.Message + "\n\n" + oException.StackTrace, "Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
#endif
                        return false;
                    }
                    return true;
                }
            }
            return false;
        }

        private bool pause_TimedHybridLog() {
            if (flag_DefaultLoggingMode == eLoggingMode.TimedHybrid) {
                if (flag_ContinuousEntryOpen) {
                    try {
                        if (memory_Writer != null) memory_Writer.Close();
                        if (memory_Stream != null) memory_Stream.Close();
                    }
                    catch (Exception oException) {
#if DEBUG
                        System.Windows.MessageBox.Show("An error occured while trying to close a log.\n\n" + oException.Message + "\n\n" + oException.StackTrace, "Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
#endif
                        if (memory_Stream != null) memory_Stream.Close();
                    }
                    flag_ContinuousEntryOpen = false;
                    memory_Stream = null;
                    memory_Writer = null;
                    return true;

                }
            }
            return false;
        }

        private bool resume_TimedHybridLog() {
            if (flag_DefaultLoggingMode == eLoggingMode.TimedHybrid) {
                if (!flag_ContinuousEntryOpen) {
                    FileInfo oFInfo = new FileInfo(memory_OpenFilename);
                    try {
                        if (oFInfo.Exists) memory_Stream = new FileStream(memory_OpenFilename, FileMode.Append);
                        else memory_Stream = new FileStream(memory_OpenFilename, FileMode.OpenOrCreate);
                        memory_Writer = new StreamWriter(memory_Stream);
                    }
                    catch (Exception oException) {
#if DEBUG
                        System.Windows.MessageBox.Show("An error occured while trying to open file '" + memory_OpenFilename + "'.\n\n" + oException.Message + "\n\n" + oException.StackTrace, "Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
#endif
                    }
                    flag_ContinuousEntryOpen = true;
                    memory_HybridBreakTimeLeft = memory_HybridBreakTime;
                    memory_Timer.Start();
                    return true;

                }
            }
            return false;
        }

        private bool close_TimedHybridLog() {
            if (flag_DefaultLoggingMode == eLoggingMode.TimedHybrid) {
                if (flag_ContinuousEntryOpen) {
                    try {
                        //if (memory_Writer != null) memory_Writer.Close();
                        if (memory_Stream != null) memory_Stream.Close();
                    }
                    catch (Exception oException) {
#if DEBUG
                        System.Windows.MessageBox.Show("An error occured while trying to close a log.\n\n" + oException.Message + "\n\n" + oException.StackTrace, "Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
#endif
                        //if (memory_Stream != null) memory_Stream.Close();
                    }
                    flag_DefaultLoggingMode = eLoggingMode.Single;
                    flag_ContinuousEntryOpen = false;
                    memory_OpenFilename = null;
                    memory_Stream = null;
                    memory_Writer = null;
                    memory_Timer.Stop();
                    return true;

                } else {
                    flag_DefaultLoggingMode = eLoggingMode.Single;
                    memory_OpenFilename = null;
                    memory_Timer.Stop();
                }
            }
            return false;
        }

        


        private void ev_Timer_Tick(object sender, EventArgs ea) {
            memory_HybridBreakTimeLeft--;
            if (memory_HybridBreakTimeLeft <= 0) {
                // deactivate
                memory_Timer.Stop();
                memory_HybridBreakTimeLeft = -1;
                pause_TimedHybridLog();
            }
        }

        #endregion
    }
}
